using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Windows;
using System.Diagnostics.Contracts;
using Konst3d.Efficiency.Suite;

namespace PEM
{
	internal partial class CountersViewModel
	{
		#region Commands

		public abstract class BaseCommand : ICommand
		{
			#region Constructor

			public BaseCommand(CountersViewModel model)
			{
				Contract.Requires(model != null);
				_model = model;
			}

			#endregion // Constructor

			#region ICommand Implementation

			public event System.EventHandler CanExecuteChanged;

			public abstract bool CanExecute(object parameter);
			public abstract void Execute(object parameter);

			protected void NotifyCanExecuteChanged(EventArgs args = null)
			{
				if (CanExecuteChanged != null)
				{
					CanExecuteChanged(this, args ?? EventArgs.Empty);
				}
			}

			#endregion

			#region Fields

			protected CountersViewModel _model;

			#endregion // Fields
		}

		public class AddCounterCommand : BaseCommand
		{
			#region Constructor

			public AddCounterCommand(CountersViewModel model) :
				base(model)
			{
				_model.SuiteOpened += OnSuiteChange;
				_model.SuiteClosed += OnSuiteChange;
				_model.SuiteCreated += OnSuiteChange;
				_model.SuiteDeleted += OnSuiteChange;
			}

			#endregion // Constructor

			#region ICommand Members

			public override bool CanExecute(object parameter)
			{
				return _model.Suite != null;
			}

			public override void Execute(object parameter)
			{
				_model.AddCounter();
			}

			#endregion

			#region Event Handlers

			private void OnSuiteChange(ViewModelBase sender)
			{
				NotifyCanExecuteChanged();
			}

			#endregion Event Handlers
		}

		public class RemoveCounterCommand : BaseCommand
		{
			#region Constructor

			public RemoveCounterCommand(CountersViewModel model) :
				base(model)
			{
				_model.CounterSelected += OnCounterSelected;
			}

			#endregion // Constructor

			#region ICommand Members

			public override bool CanExecute(object parameter)
			{
				return _model.Selected != null;
			}

			public override void Execute(object parameter)
			{
				_model.RemoveCounter();
			}

			#endregion

			#region Event Handlers

			private void OnCounterSelected(ViewModelBase sender)
			{
				NotifyCanExecuteChanged();
			}

			#endregion Event Handlers
		}

		public class EditCounterCommand : BaseCommand
		{
			#region Constructor

			public EditCounterCommand(CountersViewModel model) :
				base(model)
			{
				_model.CounterSelected += OnCounterSelected;
			}

			#endregion // Constructor

			#region ICommand Members

			public override bool CanExecute(object parameter)
			{
				return _model.Selected != null;
			}

			public override void Execute(object parameter)
			{
				_model.EditCounter();
			}

			#endregion

			#region Event Handlers

			private void OnCounterSelected(ViewModelBase sender)
			{
				NotifyCanExecuteChanged();
			}

			#endregion Event Handlers
		}

		public class ShowStatisticCommand : BaseCommand
		{
			#region Constructor

			public ShowStatisticCommand(CountersViewModel model) :
				base(model)
			{
				_model.CounterSelected += OnCounterSelected;
			}

			#endregion // Constructor

			#region ICommand Members

			public override bool CanExecute(object parameter)
			{
				return _model.Selected != null;
			}

			public override void Execute(object parameter)
			{
				_model.ShowStatistic();
			}

			#endregion

			#region Event Handlers

			private void OnCounterSelected(ViewModelBase sender)
			{
				NotifyCanExecuteChanged();
			}

			#endregion Event Handlers
		}

		/* shouldn't this be done in XAML via binding?
		public class ChangeMonitorActiveCommand : BaseCommand
		{
			#region Constructor

			public ChangeMonitorActiveCommand(MonitorsViewModel model) :
				base(model)
			{
				// _model.MonitorSelected += OnMonitorSelected;
				// _model.SelectedTaskStateChanged += OnTaskSelected;
			}

			#endregion // Constructor

			#region ICommand Members

			public override bool CanExecute(object parameter)
			{
				return _model.Selected != null && _model.Selected.State != (TaskState)parameter;
			}

			public override void Execute(object parameter)
			{
				_model.ChangeTaskState((TaskState)parameter);
			}

			#endregion

			#region Event Handlers

			private void OnTaskSelected(ViewModelBase sender)
			{
				NotifyCanExecuteChanged();
			}

			#endregion Event Handlers
		}
		*/

		#endregion // Commands

		#region Commands Collection

		public class CommandsCollection
		{
			#region Properties

			public AddCounterCommand AddCounter
			{
				get;
				private set;
			}

			public RemoveCounterCommand RemoveCounter
			{
				get;
				private set;
			}

			public EditCounterCommand EditCounter
			{
				get;
				private set;
			}

			public ShowStatisticCommand ShowStatistic
			{
				get;
				private set;
			}

			#endregion // Properties

			#region Constructor

			public CommandsCollection(CountersViewModel host)
			{
				Contract.Requires(host != null);

				AddCounter = new AddCounterCommand(host);
				RemoveCounter = new RemoveCounterCommand(host);
				EditCounter = new EditCounterCommand(host);
				ShowStatistic = new ShowStatisticCommand(host);
			}

			#endregion // Constructor
		}

		#endregion // Commands Collection

		public void AddCounter()
		{
			Contract.Requires(Suite != null);

			if (_createEditCounterDlg.ShowDialog(_parentWindow))
			{
				int id = Suite.Monitors.Add(MonitorType.Counter, _createEditCounterDlg.CounterTitle, _createEditCounterDlg.CounterDescription, DateTime.Now, true);

				var monitor = Suite.Monitors[id];
				var activeDays = _createEditCounterDlg.GetActiveWeekDays();

				for (int i = 0; i < 7; ++i)
				{
					monitor.ActiveDays.DaysOfWeek[i] = activeDays[i];
				}

				UpdateCounterList();
			}
		}

		public void RemoveCounter()
		{
			Contract.Requires(Suite != null);
			Contract.Requires(Selected != null);

			if (MessageBox.Show(_parentWindow, "Are you sure, you wish to delete this counter?", "Delete monitor?", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
			{
				Suite.Monitors.Remove(Selected.ID);
				UpdateCounterList();
			}
		}

		public void EditCounter()
		{
			Contract.Requires(Suite != null);
			Contract.Requires(Selected != null);

			if (_createEditCounterDlg.ShowDialog(_parentWindow, Selected))
			{
				Selected.Title = _createEditCounterDlg.CounterTitle;
				Selected.Description = _createEditCounterDlg.CounterDescription;

				var activeDays = _createEditCounterDlg.GetActiveWeekDays();

				for (int i = 0; i < 7; ++i)
				{
					Selected.ActiveDays.DaysOfWeek[i] = activeDays[i];
				}

				Counters.NotifyItemChanged(Selected);
			}
		}

		public void ShowStatistic()
		{
			Contract.Requires(Suite != null);
			Contract.Requires(Selected != null);

			_statisticDialog.ShowDialog(_parentWindow, Selected);
		}

		/* shouldn't this be done in XAML via binding?
		public void SetCounterActive(IMonitor monitor, bool active)
		{
			//
		}
		*/

		// show details
	}
}
